﻿using System;
using System.Drawing;
using System.Windows.Forms;
using ApplicationLibrary.DBManager;

namespace ApplicationLibrary.Preferences
{
    public partial class PreferencePanel : UserControl
    {
        public delegate void DocumentStatusChangedEventHandler(string status);

        public event DocumentStatusChangedEventHandler DocumentStatusChanged;

        public delegate void DocumentClosedEventHandler(PreferencePanel prefPanel);

        public event DocumentClosedEventHandler DocumentClose;

        public enum DBMode { Edit, Browse, Run }

        public enum ToolbarEventKind { New, Edit, Delete }

        public string ButtonText { protected set; get; }

        public Image ButtonImage { protected set; get; }

        public bool CanRemove { get; set; }

        public ToolStripDropDownButton PrefList { get { return tsddPrefList; } }

        public ToolStripButton ButtonComputer { get { return tsbComputer; } }

        public ToolStripButton ButtonUser { get { return tsbUser; } }

        public ToolStripButton ButtonApplication { get { return tsbApplication; } }

        internal ControlBinder controlBinder;

        private string ApplicationName = "";

        public DBMode DocumentMode { get; private set; }

        public bool IsNew { private set; get; }

        private BindingSource masterBind;

        #region Virtual Function

        protected virtual void OnAttachData()
        {
        }

        protected virtual void OnBindData()
        {
        }

        protected virtual void OnDisableControlsForNew()
        {
        }

        protected virtual void OnDisableControlsForEdit()
        {
        }

        protected virtual void OnFindData(MyToolStripItem tsi)
        {
        }

        protected virtual void OnNewData()
        {
            throw new Exception("OnNewData");
        }

        protected virtual bool OnLoadData()
        {
            throw new Exception("OnLoadData");
        }

        protected virtual bool OnSaveData()
        {
            throw new Exception("OnSaveData");
        }

        protected virtual void OnBeforeEdit()
        {
        }

        protected virtual bool OnUndoData()
        {
            throw new Exception("OnUndoData");
        }

        protected virtual bool OnDeleteData()
        {
            throw new Exception("OnDeleteData");
        }

        protected virtual bool IsLocked()
        {
            throw new Exception("IsLocked");
        }

        protected virtual void LockRecord()
        {
            throw new Exception("LockRecord");
        }

        protected virtual void UnLockRecord()
        {
            throw new Exception("UnLockRecord");
        }

        protected virtual bool OnToolStripButtonClick(ButtonClicked button)
        {
            throw new Exception("OnToolStripButtonClick");
        }

        protected virtual void OnValidateControl()
        {
        }

        protected virtual void OnNewEvent()
        {
            if (OnNewButton())
            {
                masterBind.CancelEdit();
                masterBind.ResetCurrentItem();
                IsNew = true;
                OnNewData();
                OnAfterAddNew();
                DocumentMode = DBMode.Edit;
            }
            ManageToolbarEvents();
            FocusOnNew();
        }

        protected virtual bool OnEditEvent()
        {
            IsNew = false;
            if (!IsLocked())
            {
                LockRecord();
                DocumentMode = DBMode.Edit;
                OnEditButton();
                CanRemove = false;
            }
            else
                return false;

            ManageToolbarEvents();
            return true;
        }

        protected virtual void OnSaveEvent()
        {
            if (!this.Validate())
                return;

            OnValidateControl();
            if (!OnBeforeSave())
                return;
            if (!OnSaveButton())
                return;
            OnAfterSave();
            if (!IsNew)
                UnLockRecord();
            DocumentMode = DBMode.Browse;
            ManageToolbarEvents();
            IsNew = false;
        }

        protected virtual void OnUndoEvent()
        {
            OnValidateControl();
            if (!OnUndoButton()) return;
            if (!IsNew)
                UnLockRecord();
            IsNew = false;
            DocumentMode = DBMode.Browse;
            ManageToolbarEvents();
        }

        protected virtual void OnDeleteEvent()
        {
            if (!OnDeleteButton()) return;
            OnAfterDelete();

            ManageToolbarEvents();
        }

        protected virtual void OnExitEvent()
        {
            if (DocumentClose != null)
                DocumentClose(this);
        }

        #endregion

        public PreferencePanel()
        {
            InitializeComponent();
            InitializeAuxComponent();
        }

        public PreferencePanel(string appName)
        {
            ApplicationName = appName;
            InitializeComponent();
            InitializeAuxComponent();
        }

        private void InitializeAuxComponent()
        {
            controlBinder = new ControlBinder();
            masterBind = new BindingSource();
            IsNew = false;
            CanRemove = true;
            DocumentMode = DBMode.Browse;
        }

        public void AttachData(object obj)
        {
            masterBind.DataSource = obj;
            masterBind.CurrencyManager.Refresh();
        }

        protected override void OnLoad(EventArgs e)
        {
            OnAttachData();
            ManageOperationButton();

            OnBindData();
            if (controlBinder != null)
                controlBinder.Enable(false);

            base.OnLoad(e);
        }

        #region Enable Disable OperationButton

        private void ManageOperationButton()
        {
            try
            {
                tsbNew.Enabled = DocumentMode == DBMode.Browse;
                tsbEdit.Enabled = tsddPrefList.DropDownItems.Count > 0 && DocumentMode == DBMode.Browse;
                tsbDelete.Enabled = tsddPrefList.DropDownItems.Count > 0 && DocumentMode == DBMode.Browse;
                tsbUndo.Enabled = DocumentMode == DBMode.Edit;
                tsbSave.Enabled = DocumentMode == DBMode.Edit;
                tsddPrefList.Enabled = DocumentMode == DBMode.Browse;
                tsbComputer.Enabled = DocumentMode != DBMode.Browse;
                tsbUser.Enabled = DocumentMode != DBMode.Browse;
                tsbApplication.Enabled = DocumentMode != DBMode.Browse && ApplicationName != string.Empty;
            }
            catch (Exception exc)
            {
                MessageBox.Show(exc.Message);
            }
        }

        #endregion

        #region virtual override function

        protected virtual bool OnNewButton()
        {
            if (OnBeforeAddNew())
            {
                IsNew = true;
                OnNewData();
                OnPrepareAuxData();
                return true;
            }

            return false;
        }

        protected virtual void OnEditButton()
        {
            CanRemove = false;
            IsNew = false;
            OnBeforeEdit();
            OnPrepareAuxData();
        }

        protected virtual bool OnSaveButton()
        {
            return OnSaveData();
        }

        protected virtual bool OnDeleteButton()
        {
            if (OnBeforeDelete())
            {
                if (!IsLocked())
                {
                    IsNew = false;
                    return OnDeleteData();
                }
            }

            return false;
        }

        protected virtual bool OnUndoButton()
        {
            if (OnBeforeUndo())
            {
                masterBind.EndEdit();
                masterBind.CancelEdit();
                CanRemove = true;
                return true;
            }
            return false;
        }

        protected virtual bool OnBeforeClosing()
        {
            if (DocumentMode == DBMode.Edit)
            {
                if (MessageBox.Show
                    (
                        Properties.Resources.Exit_Close,
                        Properties.Resources.Warning,
                        MessageBoxButtons.YesNo,
                        MessageBoxIcon.Question
                    ) == DialogResult.Yes)
                {
                    OnUndoData();
                    return false;
                }
                else return true;
            }
            else return false;
        }

        protected virtual void OnPrepareAuxData()
        {
        }

        protected virtual bool OnBeforeAddNew()
        {
            return true;
        }

        protected virtual bool OnAfterAddNew()
        {
            return true;
        }

        protected virtual void FocusOnNew()
        {
        }

        protected virtual bool OnBeforeSave()
        {
            return true;
        }

        protected virtual bool OnAfterSave()
        {
            OnPrepareAuxData();
            return true;
        }

        protected virtual bool OnBeforeDelete()
        {
            return MessageBox.Show(
                    Properties.Resources.Msg_Delete,
                    Properties.Resources.Warning,
                    MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes;
        }

        protected virtual bool OnAfterDelete()
        {
            masterBind.CurrencyManager.Refresh();
            return true;
        }

        protected virtual bool OnPrintDocument(string sender, printerForm pf)
        {
            return true;
        }

        protected virtual bool OnBeforeUndo()
        {
            return MessageBox.Show
                (
                Properties.Resources.Exit_Undo,
                Properties.Resources.Warning,
                MessageBoxButtons.YesNo,
                MessageBoxIcon.Question
                ) == DialogResult.Yes;
        }

        #endregion

        private void tsddPrefList_DropDownItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {
            MyToolStripItem tsi = (MyToolStripItem)e.ClickedItem;
            OnFindData(tsi);
        }

        private void tsbNew_Click(object sender, EventArgs e)
        {
            OnNewEvent();
        }

        private void tsbEdit_Click(object sender, EventArgs e)
        {
            OnEditEvent();
        }

        private void tsbSave_Click(object sender, EventArgs e)
        {
            OnSaveEvent();
        }

        private void tsbUndo_Click(object sender, EventArgs e)
        {
            OnUndoEvent();
        }

        private void tsbDelete_Click(object sender, EventArgs e)
        {
            OnDeleteEvent();
        }

        private void tsbExit_Click(object sender, EventArgs e)
        {
            OnExitEvent();
        }

        protected void UpdateToolbarIcon(MyToolStripItem tsi)
        {
            UpdateToolbarIcon(tsi.HasComputer, tsi.HasUser, tsi.HasApplication);
        }

        protected void UpdateToolbarIcon(bool hasComputer, bool hasUser, bool hasApplication)
        {
            tsbComputer.Image = hasComputer
                ? Properties.Resources.ComputerSelect
                : Properties.Resources.Computer;
            tsbUser.Image = hasUser
                ? Properties.Resources.UserSelect
                : Properties.Resources.User;
            tsbApplication.Image = hasApplication
                ? Properties.Resources.ApplicationSelect
                : Properties.Resources.Application;
        }

        private void ManageToolbarEvents()
        {
            ManageOperationButton();
            if (controlBinder != null)
                controlBinder.Enable(DocumentMode == DBMode.Edit);

            if (DocumentMode == DBMode.Edit)
            {
                if (IsNew)
                {
                    OnDisableControlsForNew();
                    DocumentStatusChanged(Properties.Resources.Doc_New);
                }
                else
                {
                    OnDisableControlsForEdit();
                    DocumentStatusChanged(Properties.Resources.Doc_Edit);
                }

                if (controlBinder != null)
                    controlBinder.SetFocus();
            }
            else
                DocumentStatusChanged(Properties.Resources.Doc_Ready);
        }

        public void BindControl(Control control)
        {
            controlBinder.Bind(control);
        }

        public Binding BindControl(Control control, string datamember)
        {
            return BindControl(control, datamember, "Text");
        }

        public Binding BindControl(Control control, string datamember, string property)
        {
            Binding objBind = new Binding(property, masterBind, datamember);
            control.DataBindings.Add(objBind);
            controlBinder.Bind(control);

            return objBind;
        }

        public Binding BindObject(IBindableComponent bindableObj, string datamember, string property)
        {
            Binding objBind = new Binding(property, masterBind, datamember);
            controlBinder.Bind(bindableObj);
            bindableObj.DataBindings.Add(objBind);
            return objBind;
        }

        private void tsbComputer_Click(object sender, EventArgs e)
        {
            if (!IsNew)
                return;

            tsbComputer.Image = OnToolStripButtonClick(ButtonClicked.Computer)
                ? Properties.Resources.ComputerSelect
                : Properties.Resources.Computer;
        }

        private void tsbUser_Click(object sender, EventArgs e)
        {
            if (!IsNew)
                return;

            tsbUser.Image = OnToolStripButtonClick(ButtonClicked.User)
                ? Properties.Resources.UserSelect
                : Properties.Resources.User;
        }

        private void tsbApplication_Click(object sender, EventArgs e)
        {
            if (!IsNew)
                return;

            tsbApplication.Image = OnToolStripButtonClick(ButtonClicked.Application)
                 ? Properties.Resources.ApplicationSelect
                : Properties.Resources.Application;
        }
    }
}